\section{NAME\label{NAME}\index{NAME}}


Bench::Test - Automatizacion, analisis y comparacion de rendimiento

\section{SYNOPSIS\label{SYNOPSIS}\index{SYNOPSIS}}
\begin{verbatim}
  use Bench::Test;
\end{verbatim}
\begin{verbatim}
  # New Bench::Test using configuration file
  my $bt = Bench::Test->new(
     config_file => 'maketest.conf'
  );
\end{verbatim}
\begin{verbatim}
  # New Bench::Test specifying all parameters manually
  my $bt = Bench::Test->new(
      tests       => \@TESTS,
      table       => \@TABLE,
      visual      => \@VISUAL,
      experiments => \%EXPERIMENTS,
      selected    => \@SELECTED,
  );
\end{verbatim}
\begin{verbatim}
  # Executing "make test"
  $bt->make_test;
\end{verbatim}
\begin{verbatim}
  # Executing "create test"
  $bt->create_tests;
\end{verbatim}
\section{DESCRIPTION\label{DESCRIPTION}\index{DESCRIPTION}}


El objeto Bench::Test permite automatizar, analizar y comparar
diversas ejecuciones realizadas en tiempo real, en el pasado y 
en la maquina local y maquinas remotas simultaneamente. Cuenta con
dos metodos principales: 'make\_test' y 'create\_tests'.



Los parametros de configuracion de las ejecuciones pueden 
definirse mediante un fichero de configuracion (por defecto,
maketest.conf) o mediante parametros en el constructor.



La salida de las ejecuciones es filtrada mediante un
conjunto de expresiones regulares indicadas por el usuario.
El resultado es devuelto al usuario por pantalla

\subsection*{Example\label{Example}\index{Example}}


Supongamos un programa cuya salida sea la siguiente:

\begin{verbatim}
  ~/projects/Bench-Test/examples/mm$ ./mm dat/mm_200.dat 
  Filas primera matriz: 200
  Filas segunda matriz: 200
  Columnas segunda matriz: 200
  Time of product: 0.210942
  Result: 4102
\end{verbatim}


Supongamos que queremos ejecutar dicho programa con
diferentes parametros de entrada y comparar las salidas.



La idea es que el usuario especifique las caracteristicas
del experimento y ejecute el metodo 'make\_test'. El metodo
realizara las ejecuciones para cada conjunto de parametros,
analiza las salidas, las formatea y las muestra por pantalla.



Ejecutando el script 'maketest':

\begin{verbatim}
  #!/usr/bin/perl -w
\end{verbatim}
\begin{verbatim}
  use strict;
  use Pod::Usage;
  use Getopt::Long;
  use Bench::Test;
  use Carp;
\end{verbatim}
\begin{verbatim}
  # MAIN ========================================================================
\end{verbatim}
\begin{verbatim}
  my $config_file = './maketest.conf';   # By default is 'maketest.conf'
\end{verbatim}
\begin{verbatim}
  my $bench = new Bench::Test(
    config_file => $config_file,
  );
\end{verbatim}
\begin{verbatim}
  $bench->make_tests;
\end{verbatim}


Se obtiene una salida similar a la siguiente:

\begin{verbatim}
  ~/projects/Bench-Test/examples/mm$ maketest
  TEST    FILE    DIM             TIME(BASE_feb)  TIME(LOCAL)     TIME(ORION)
  OK      mm_100  100:100:100     0.011588        0.026716        0.011582
  OK      mm_200  200:200:200     0.091474        0.202479        0.092152
  OK      mm_300  300:300:300     0.432486        1.000445        0.432919
  OK      mm_500  500:500:500     3.923428        5.067983        2.547144
\end{verbatim}
\section{METHODS\label{METHODS}\index{METHODS}}
\subsection*{The constructor \texttt{new}\label{The_constructor_new}\index{The constructor new}}


Vease una llamada tipica:

\begin{verbatim}
  # New Bench::Test using configuration file
  my $bt = Bench::Test->new(
     config_file => 'maketest.conf'
  );
\end{verbatim}
\begin{verbatim}
  # New Bench::Test specifying all parameters manually
  my $bt = Bench::Test->new(
      tests       => \@TESTS,
      table       => \@TABLE,
      visual      => \@VISUAL,
      experiments => \%EXPERIMENTS,
      selected    => \@SELECTED,
  );
\end{verbatim}


Este metodo devuelve una nueva instancia de un objeto
Bench::Test.



Los parametros de configuracion puedn ser expresados
en un fichero de configuracion, con parametros
del constructor o con ambos. En caso de conflicto
tienen mayor prioridad los parametros definidos en 
el constructor y no en el fichero de configuracion.



Los nombres de los parametros son exactamente los 
mismos en el constructor y en el fichero de configuracion
excepto que en el fichero se escriben en mayusculas.

\subsection*{The \texttt{make\_test} method\label{The_make_test_method}\index{The make\ test method}}


El metodo \texttt{make\_test} se encarga de automatizar las ejecucione
definidas previamente por el usuario. A su vez, analiza las salidas
y las formatea para mostrarlas al usuario y/o almacenarlas en 
ficheros de texto con distintos formatos. (Vease Bench::Test::View,
Bench::Test::Local y Bench::Test::Remote)

\subsection*{The \texttt{create\_tests} method\label{The_create_tests_method}\index{The create\ tests method}}


El metodo \texttt{create\_tests} solamente automatiza las ejecuciones
almacenando las salidas en ficheros de texto nombrados con
extension .base (Vease Bench::Test::Base) para un posterior
procesamiento.

\section{THE CONFIGURATION FILE\label{THE_CONFIGURATION_FILE}\index{THE CONFIGURATION FILE}}


Vease un ejemplo de fichero de configuracion

\begin{verbatim}
  ~/projects/Bench-Test/examples/mm$ cat maketest.conf
\end{verbatim}
\begin{verbatim}
   @TESTS = (
      mm_100 => './dat/mm_100.dat',
      mm_200 => './dat/mm_200.dat',
      mm_300 => './dat/mm_300.dat',
     mm_500 => './dat/mm_500.dat',
   );
\end{verbatim}
\begin{verbatim}
   @TABLE         = (
      #TEST metafield
      #FILE metafield
\end{verbatim}
\begin{verbatim}
      DIM  => {
                 REGEXP => 'primera\s*matriz:\s*(.*)\n.*?:\s*(.*)\n.*?:\s*(.*)\n',
                 CODE   => sub { return "$1:$2:$3"; }
              },
      RES  => { REGEXP => 'Result:\s+(.*)\n' }, 
      TIME => { REGEXP => 'Time of product:\s*(.*)\n' },
   );
\end{verbatim}
\begin{verbatim}
   @UNIQUE   = qw(DIM);
   @VISUAL   = qw(TEST FILE DIM TIME);
   @SELECTED = qw(BASE_feb LOCAL ORION);
\end{verbatim}
\begin{verbatim}
   sub Bench::Test::Entry::is_OK { Code to check if test is OK }
\end{verbatim}
\begin{verbatim}
   %EXPERIMENTS = ( 
      'BASE_feb' => Bench::Test::Base->new ( 
                     WORKDIR   => './base_FEB'
                  ),
      'LOCAL'    => Bench::Test::Local->new  (
                     WORKDIR   => '.',
                     EXECUTABLE => './mm',
                     OUTPUTFILE => 'output.dat',
                     BASEDIR   => './base_FEB',
                  ),
      'ORION'    => Bench::Test::Remote->new (
                     HOST       => 'user@host',
                     WORKDIR    => '/home/user/mm',
                     EXECUTABLE => 'mm',
                     BASEDIR    => './base_ORION',
                     OUTPUTFILE => 'output.dat',
                     PREAMBLE   => sub {
                        my $machine = shift;
                        $machine->put(['mm.tar.gz']);
                        $machine->system('tar xfz mm.tar.gz');
                        $machine->chdir('mm');
                        $machine->system('make');
                     },
                     POSTAMBLE  => sub {
                        my $machine = shift;
                        $machine->chdir('..');  
                        $machine->system('rm -rf mm');
                        $machine->system('rm mm.tar.gz');
                    },
                  ),
   );
\end{verbatim}
\subsection*{The \texttt{@TABLE} field\label{The_TABLE_field}\index{The @TABLE field}}


The \texttt{@TABLE} field is used to specify the regular expression
defining the chunk of output we are interested in. 
The key is the name of the field (\texttt{DIM}, \texttt{TIME}, etc in the example).
The entry \texttt{REGEXP} contains the string defining the 
regular expression. The subexpression between parenthesis
is the one that defines the chunk or observable we are interested in. 
The rest of the string defines the context in which the 
the observable appears.



Adicionalmente puede incluirse una entrada \texttt{CODE} especificando
una rutina configurable por el usuario que permite una mayor
versatilidad. La entrada \texttt{CODE} siempre tendra una entrada
\texttt{REGEXP} asociada, que sera la que dispare la rutina en caso
de casar con la salida del programa. Ejemplo:

\begin{verbatim}
   @TABLE         = (
      #TEST metafield
      #FILE metafield
\end{verbatim}
\begin{verbatim}
      DIM  => {
                REGEXP => 'primera\s*matriz:\s*(.*)\n.*?:\s*(.*)\n.*?:\s*(.*)\n',
                CODE   => sub { return "$1:$2:$3"; }
              },
      RES  => { REGEXP => 'Result:\s+(.*)\n' },
      TIME => { REGEXP => 'Time of product:\s*(.*)\n' },
   );
\end{verbatim}


Para la entrada \texttt{DIM} se comprueba si la entrada casa con 
la expresion regular (observese que cuenta con tres parentesis) y
a continuacion se ejecuta el codigo si asi fuera necesario. El codigo
devolveria la cadena que sera mostrada al usuario. En este caso, la
concatenacion de las tres dimensiones de una matriz.

\subsection*{The \texttt{@TESTS} list\label{The_TESTS_list}\index{The @TESTS list}}


La lista \texttt{@TESTS} contiene una entrada por cada uno de los tests
que queramos realizar. Cada entrada esta formada por una cadena
que indica los parametros con los que se ejecuta el programa 
ejecutable que se esta analizando. Ejemplo:

\begin{verbatim}
   @TESTS = (
      mm_100 => './dat/mm_100.dat',
      mm_200 => './dat/mm_200.dat',
      mm_300 => './dat/mm_300.dat',
      mm_500 => './dat/mm_500.dat',
   );
\end{verbatim}


Se proveen dos rutinas de apoyo al usuario que permiten definir
el array \texttt{@TESTS} mediante el contenido de un fichero o mediante
un glob.



La siguiente sentencia lee el fichero \texttt{myfile.test} linea a linea
obteniendo los pares (clave,valor) separados por ':'

\begin{verbatim}
  @TESTS = get_tests_from_file('myfile.test')
\end{verbatim}


Si el contenido del fichero \texttt{myfile.test} fuera el siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ cat myfile.test
   test1:-n 100 test1.dat
   test2:-n 200 test2.dat
   test3:-n 300 test2.dat
\end{verbatim}


El resultado de \texttt{get\_tests\_from\_file} y, por tanto, el contenido
del array \texttt{@TESTS} seria:

\begin{verbatim}
   @TESTS = (
      test1 => '-n 100 test1.dat',
      test2 => '-n 200 test2.dat',
      test3 => '-n 300 test3.dat'
   );
\end{verbatim}


La rutina \texttt{get\_tests\_from\_glob} supone que el programa recibe
un solo parametro: el nombre de un fichero. Por tanto, suponiendo
un directorio como el siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm/dat$ ls -l
   total 1548
   -rw-r--r-- 1 alu2807 alu2807   40212 2008-02-11 09:36 mm_100.dat
   -rw-r--r-- 1 alu2807 alu2807  160412 2008-02-11 09:36 mm_200.dat
   -rw-r--r-- 1 alu2807 alu2807  360612 2008-02-11 09:36 mm_300.dat
   -rw-r--r-- 1 alu2807 alu2807 1001012 2008-02-11 09:36 mm_500.dat
\end{verbatim}


Y una llamada como la siguiente:

\begin{verbatim}
   @TESTS = get_tests_from_glob('*.dat');
\end{verbatim}


Obtendriamos el siguiente array \texttt{@TESTS}:

\begin{verbatim}
   @TESTS = (
      mm_100 => 'mm_100.dat',
      mm_200 => 'mm_200.dat',
      mm_300 => 'mm_300.dat',
      mm_500 => 'mm_500.dat'
   );
\end{verbatim}
\subsection*{The \texttt{@VISUAL} list\label{The_VISUAL_list}\index{The @VISUAL list}}


The \texttt{@VISUAL} list determines what fields will be displayed 
in standard output. The names of the fields are 
the keys of \texttt{@TABLE} (\texttt{DIM}, \texttt{TIME}, etc). Example:

\begin{verbatim}
  @VISUAL = qw(TEST FILE DIM TIME);
\end{verbatim}


such definition will produce an output like:

\begin{verbatim}
  ~/projects/Bench-Test/mm$ ./maketest 
  TEST    FILE    DIM     TIME(BASE_feb)  TIME(LOCAL)     TIME(ORION)
  OK      mm_100  100:100:100     0.014589        0.013538        0.009383
  OK      mm_200  200:200:200     0.109944        0.177367        0.073903
  OK      mm_300  300:300:300     0.361250        0.528413        0.359595
  OK      mm_500  500:500:500     1.934884        2.993155        1.886891
\end{verbatim}


Observese que algunos de los campos estan repetidos para
cada uno de los \texttt{EXPERIMENTS} y otros no. Esto es asi, porque
existen campos que son invariables cualquiera que sea la maquina
de ejecucion. Por ejemplo: la entrada de problema, las dimensiones.



Para indicar que campos no deben duplicarse por tratarse de campos unicos
utilizamos la lista \texttt{UNIQUE}.

\subsection*{The \texttt{@UNIQUE} list\label{The_UNIQUE_list}\index{The @UNIQUE list}}


Indica los campos para los que el resultado de la ejecucion no variara
de una maquina a otra. Ejemplo:

\begin{verbatim}
  @UNIQUE = qw(DIM);
\end{verbatim}
\subsection*{The \texttt{@SELECTED} list\label{The_SELECTED_list}\index{The @SELECTED list}}


Indica los experimentos que seran ejecutados. Similar a \textbf{@VISUAL} pero
con los experimentos.

\subsection*{The \texttt{\%EXPERIMENTS} hash\label{The_EXPERIMENTS_hash}\index{The \%EXPERIMENTS hash}}


Este hash almacena la informacion acerca de las distintas maquinas remotas,
maquina local y resultados de ejecuciones anteriores (base).



La clave es el nombre que se mostrara al usuario. El valor puede ser uno de 
los siguientes objetos:

\begin{verbatim}
  Bench::Test::Base
  Bench::Test::Local
  Bench::Test::Remote
\end{verbatim}


Los tres objetos cuentan con constructores distintos, pero dos metodos
identicos, con la misma interfaz:

\begin{verbatim}
  get_result  ($params, $test)
  save_result ($params, $test)
\end{verbatim}


Estos metodos se encargan de devolver el resultado de la ejecucion
del programa del usuario con los parametros especificados en \texttt{\$params}
(get\_result) o almacenarlo en el correspondiente archivo .base (save\_result).



El parametro \texttt{\$test} se utiliza unicamente en el objeto \texttt{Bench::Test::Base}
e indica el nombre del test al que se quiere acceder. El resultado de
la salida de una ejecucion anterior estara almacenado en el fichero \texttt{\$test.base}
dentro del directorio \texttt{WORKDIR} de dicho objeto.

\subsection*{The \texttt{Bench::Test::Base} object\label{The_Bench::Test::Base_object}\index{The Bench::Test::Base object}}


Su constructor acepta un unico parametro (\texttt{WORKDIR}) y es obligatorio. Este parametro
indica el directorio donde se encuentran los fichero .base (salidas de
las ejecuciones almacenadas).

\subsection*{The \texttt{Bench::Test::Local} object\label{The_Bench::Test::Local_object}\index{The Bench::Test::Local object}}


Su constructor acepta los siguientes parametros:

\begin{description}

\item[{WORKDIR}] \mbox{}

Indica el directorio de trabajo del proyecto.


\item[{EXECUTABLE}] \mbox{}

Nombre del fichero ejecutable. Ruta relativa a partir
del directorio de trabajo.


\item[{BASEDIR}] \mbox{}

Opcional. Indica el directorio donde se almacenaran
los ficheros .base en caso de querer crearlo. Vease Bench::Test::Base


\item[{OUTPUTFILE}] \mbox{}

Opcional. Nombre del fichero de donde se leerá l
salida del programa. Si no se especifica, se toma
la salida por STDOUT.

\end{description}
\subsection*{The \texttt{Bench::Test::Remote} object\label{The_Bench::Test::Remote_object}\index{The Bench::Test::Remote object}}


Su constructor acepta los siguientes parametros:

\begin{description}

\item[{WORKDIR}] \mbox{}

Mismo significado que para \texttt{Bench::Test::Local}.


\item[{EXECUTABLE, BASEDIR, OUTPUTFILE}] \mbox{}

Mismo significado que para \texttt{Bench::Test::Local}.


\item[{HOST}] \mbox{}

Usuario y host de la maquina remota en el formato \texttt{user@host}.


\item[{PREAMBLE}] \mbox{}

Rutina que sera ejecutada antes de realizar ningun test. Se
ejecuta en la maquina local, pero se le pasa un objeto de tipo
GRID::Machine conectado a la maquina remota, con lo que se le
permite al usuario aprovechar toda su funcionalidad. Vease la
documentacion de \texttt{GRID::Machine}


\item[{POSTAMBLE}] \mbox{}

Identico a \texttt{PREAMBLE} salvo que se ejecuta despues de haber
realizado todos los tests.

\end{description}
\section{SEE ALSO\label{SEE_ALSO}\index{SEE ALSO}}


Bench::Test::Base, Bench::Test::Local, Bench::Test::Remote, Bench::Test::View,
GRID::Machine

\section{AUTHOR\label{AUTHOR}\index{AUTHOR}}


Casiano Rodriguez-Leon
Juan Antonio Gomez Cabo



$<$casiano@ull.es$>$
$<$gomezcabo@yahoo.es$>$

\section{COPYRIGHT AND LICENSE\label{COPYRIGHT_AND_LICENSE}\index{COPYRIGHT AND LICENSE}}


Copyright (C) 2006 by Casiano Rodriguez Leon, Juan Antonio Gomez Cabo



This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.4 or,
at your option, any later version of Perl 5 you may have available.

